<?php
/**
 * The world of warcraft armory library was created by Marc Binder. The called
 * product will be deployed by Tof Technologies, Germany. All sources contain to 
 * the New BSD Licence. Self created extensions can be contained in the hall of 
 * fame. So the community has the chance to get a overview of all parsers and
 * handlers, which are really effective.
 * 
 * Get more informations:
 * http://code.google.com/p/warcraftarmory/
 * 
 * @author      Marc Binder <marcandrebinder@gmail.com>
 * @copyright   (c) Tof Technologies, Germany - 2010
 * @license     New BSD Licence
 * @package     Wow_Armory
 * @version     $Id$
 */

/**
 * Wow_Armory_Core_Cache_File
 * 
 * @category    Wow_Armory
 * @package     Core
 * @subpackage  Cache File
 * @example     n/A
 */
class Wow_Armory_Core_Cache_File
    extends Wow_Armory_Core_Cache_Abstract
    implements Wow_Armory_Core_Cache_Interface
{
    
    const EXPR_META_VAR = 93293; 
    
    protected $_config = array();

    protected $_cacheEnd = '.data.cache';
    
    protected $_metaEnd = '.meta.cache';

    protected $_dateFormat = 'Y-m-d H:i';
    
    public function __construct($config = false)
    {
        if (is_array($config)) {
            $this->_initConfig($config);
        }
        
        if ($config instanceof ArrayObject) {
            $this->_initConfig($config->getArrayCopy());
        }
        
        $this->setName('File');
    }
    
    protected function _initConfig(Array $config)
    {
        $needs = array(
            'dir' => 'is_string',
            'suffix' => 'is_string',
            'automaticSerialize' => 'is_bool'
        );
        
        foreach ($needs as $need => $method) {
            if (!in_array($need, array_keys($config))) {
                throw new Wow_Armory_Exception('', 1020);
            } else {
                if (!$method($config[$need])) {
                    throw new Wow_Armory_Exception('', 1021);
                }
                
                $this->_config[$need] = $config[$need];
            }
        }
    }
    
    protected function _getDir()
    {
        return $this->_config['dir'];
    }
    
    protected function _getSuffix()
    {
        return $this->_config['suffix'];
    }
    
    protected function _getAutomaticSerialize()
    {
        return $this->_config['automaticSerialize'];
    }
    
    protected function _checkConfig()
    {
        if (!is_writable($this->_getDir())) {
            throw new Wow_Armory_Exception('', 1022);
        }
        
        // FIXME: Implement a regex method to check the given name for only characters like a string.
        
        return true;
    }
    
    public function load($name)
    {
        if (empty($name)
            || !is_string($name)
        ) {
            throw new Wow_Armory_Exception('', 1023);
        }
        
        $meta  = $this->_getDir() . '/' .$this->_getSuffix() . $name . $this->_metaEnd;
        $cache = $this->_getDir() . '/' .$this->_getSuffix() . $name . $this->_cacheEnd;
        
        if (!file_exists($meta) 
            || !file_exists($cache)
        ) {
            return self::EXPR_META_VAR;
        }
        
        $metaData  = file_get_contents($meta);
        $cacheData = file_get_contents($cache);
        $expire    = date($this->_dateFormat, $metaData);

        if ($this->_getAutomaticSerialize()) {
            $cacheData = unserialize($cacheData);
        }
        
        if (date('Y-m-d H:i', $metaData) < date($this->_dateFormat)) {
            return self::EXPR_META_VAR;
        }
        
        return $cacheData;
    }
    
    public function isExpired($data)
    {
        if ($data == self::EXPR_META_VAR) {
            return true;
        }
        
        return false;
    }
    
    public function write($name, $time, $data)
    {
        if ($this->_checkConfig()) {
            $this->_writeMetaFile($name, $time);
            $this->_writeCacheFile($name, $data);
        }
        
        return false;
    }
    
    protected function _writeCacheFile($name, $data)
    {
        if ($this->_getAutomaticSerialize()) {
            $data = serialize($data);
        }
        
        file_put_contents(
            $this->_getDir() . '/' . $this->_getSuffix() . $name . $this->_cacheEnd,
            $data
        );
    }
    
    protected function _writeMetaFile($name, $time)
    {
        file_put_contents(
            $this->_getDir() . '/' . $this->_getSuffix() . $name . $this->_metaEnd,
            strtotime(date($this->_dateFormat)) + $time
        );
    }
    
} 